﻿/******************************************************************************
*   Project:		DotNetCRM 
*	Filename:		DomainObjectTests.cs
*	Author:			Kristopher Cargile <kris@kriscargile.com>
*	Date Created:	January 29, 2010
*******************************************************************************
*	Change History: 
*******************************************************************************
* IMPORTANT GNU LICENSE INFORMATION. DO NOT REMOVE THIS SECTION!
*
* DotNetCRM :: Copyright (c) 2005-2010, Cargile Technology Group, LLC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
******************************************************************************/

using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
using Microsoft.Practices.EnterpriseLibrary.Validation;
using NUnit.Framework;
using Rhino.Mocks;

namespace DotNetCRM.Core.Tests
{
    [TestFixture]
    public class DomainObjectTests
    {
        private MockRepository _mocks;
        private DomainObject _mockTarget;

        [TestFixtureSetUp]
        public void Setup()
        {
            _mocks = new MockRepository();

            _mockTarget = _mocks.PartialMock<DomainObject>();
            _mockTarget.Id = 1;

            // RowVersion is protected; set version using reflection...
            Type type = _mockTarget.GetType();
            PropertyInfo prop = type.GetProperty("RecordVersion");
            prop.SetValue(_mockTarget, 2, null);

            _mocks.ReplayAll();
        }

        [TestFixtureTearDown]
        public void Teardown()
        {
            _mocks.VerifyAll();
        }

        [Test]
        public void Initialize()
        {
            Assert.AreEqual(1, _mockTarget.Id);
            Assert.AreEqual(_mockTarget.Created, _mockTarget.Modified);
            Assert.AreEqual(_mockTarget.CreatedBy, _mockTarget.ModifiedBy);
            Assert.AreEqual(Environment.UserName, _mockTarget.CreatedBy);
            Assert.AreEqual(2, _mockTarget.RecordVersion);
        }

        [Test]
        public void Hash()
        {
            int hash = _mockTarget.GetHashCode();
            Assert.AreEqual(_mockTarget.Id, hash);
        }

        [Test]
        public void AreEqual()
        {
            Assert.AreEqual(_mockTarget, _mockTarget);
            Assert.IsTrue(_mockTarget.Equals(_mockTarget));
        }

        [Test]
        public void ConvertToDataSet()
        {
            IList<DomainObject> aList = new List<DomainObject>(1) { _mockTarget };
            DataSet rslt = DomainObject.ToDataSet(aList);

            Assert.IsNotNull(rslt);
            Assert.IsTrue(rslt.Tables.Count > 0);

            DataTable tbl = rslt.Tables[0];

            Assert.AreEqual("DomainObject", tbl.TableName);
            Assert.AreEqual(1, tbl.Rows.Count);

            PropertyInfo[] props = _mockTarget.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            Assert.IsTrue(tbl.Columns.Count > 0);
            Assert.IsTrue(props.Length >= tbl.Columns.Count);

            foreach (PropertyInfo info in props)
            {
                // we can't match the exact number of columns here, becuase of mocking
                if (tbl.Columns.Contains(info.Name))
                {
                    object origValue = info.GetValue(_mockTarget, null);
                    Assert.AreEqual(tbl.Rows[0][info.Name], origValue);
                }
            }
        }

        [Test]
        public void ConvertToDataSetEmptyList()
        {
            IList<DomainObject> aList = new List<DomainObject>();
            DataSet rslt = DomainObject.ToDataSet(aList);

            Assert.IsNotNull(rslt);
            Assert.AreEqual(0, rslt.Tables.Count);
        }

        [Test]
        public void ConvertToDataSetWithNullList()
        {
            Assert.Throws<ArgumentNullException>(delegate { DomainObject.ToDataSet<DomainObject>(null); });
        }

        [Test]
        public void ConvertToDataTable()
        {
            IList<DomainObject> aList = new List<DomainObject>(1) { _mockTarget };
            DataTable tbl = DomainObject.ToDataTable(aList);

            Assert.AreEqual("DomainObject", tbl.TableName);
            Assert.AreEqual(1, tbl.Rows.Count);

            PropertyInfo[] props = _mockTarget.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
            Assert.IsTrue(tbl.Columns.Count > 0);
            Assert.IsTrue(props.Length >= tbl.Columns.Count);

            foreach (PropertyInfo info in props)
            {
                // we can't match the exact number of columns here, becuase of mocking
                if (tbl.Columns.Contains(info.Name))
                {
                    object origValue = info.GetValue(_mockTarget, null);
                    Assert.AreEqual(tbl.Rows[0][info.Name], origValue);
                }
            }
        }

        [Test]
        public void ConvertToDataTableWithNullList()
        {
            Assert.Throws<ArgumentNullException>(delegate { DomainObject.ToDataTable<DomainObject>(null); });
        }

        [Test]
        public void Validate()
        {
            ValidationResults rslts = _mockTarget.Validate();
            Assert.IsNotNull(rslts);
        }

        [Test]
        public void ValidateNullObject()
        {
            Assert.Throws<ArgumentNullException>(delegate { DomainObject.Validate<DomainObject>(null); });
        }

        [Test]
        public void ValidateEmptyRuleset()
        {
            Assert.Throws<ArgumentNullException>(delegate { DomainObject.Validate(_mockTarget); });
        }
    }
}